%%%---------------------------------------------------------------------------------------
%%% @author    Stuart Jackson <sjackson@simpleenigma.com> [http://erlsoft.org]
%%% @copyright 2006 - 2007 Simple Enigma, Inc. All Rights Reserved.
%%% @doc       Erlang Internet Framework
%%% @reference See <a href="http://erlsoft.org/" target="_top">Erlang Software Framework</a> for more information
%%% @reference See <a href="http://eif.googlecode.com" target="_top">EIF Google Code Repository</a> for more information
%%% @version   0.0.1
%%% @since     0.0.1
%%% @end
%%%
%%%
%%% The MIT License
%%%
%%% Copyright (c) 2007 Stuart Jackson, Simple Enigma, Inc. All Righs Reserved
%%%
%%% Permission is hereby granted, free of charge, to any person obtaining a copy
%%% of this software and associated documentation files (the "Software"), to deal
%%% in the Software without restriction, including without limitation the rights
%%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
%%% copies of the Software, and to permit persons to whom the Software is
%%% furnished to do so, subject to the following conditions:
%%%
%%% The above copyright notice and this permission notice shall be included in
%%% all copies or substantial portions of the Software.
%%%
%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
%%% THE SOFTWARE.
%%%
%%%
%%%---------------------------------------------------------------------------------------
-module(eif_update).
-author('sjackson@simpleenigma.com').

-include("../include/eif.hrl").
-define(IP_PREFIX,10).

-export([check/1,version_to_tuple/1,lookup/1,compare/2,get/1,upgrade/1]).


upgrade(App) ->
	case check(App) of
		{ok,upgrade,{Ver1,Ver2}} ->
			io:format("Upgrading ~p from ~s to ~s ...~n",[App,version_to_list(Ver1),version_to_list(Ver2)]);
		{ok,development,{Ver1,Ver2}} ->
			io:format("Not Upgrading: ~p is already at version ~s and only ~s is online.~n",[App,version_to_list(Ver1),version_to_list(Ver2)]);
		{ok,current,{Ver1,_Ver2}} ->
			io:format("Not Upgrading: ~p is already at current version (~s).~n",[App,version_to_list(Ver1)]);
		{error,app_not_found} ->
			case lookup(App) of
				{ok,Ver} ->
					io:format("Installing ~p version ~s ...~n",[App,version_to_list(Ver)]);
				{error,Reason} ->
					io:format("Not Upgrading: ~p~n",[Reason])
			end;
		{error,Reason} ->
			io:format("Not Upgrading: ~p~n",[Reason])
	end.



check(App) ->
	case application:load(App) of
		ok -> check2(App);
		{error,{already_loaded,App}} -> check2(App);
		{error,_Reason} -> {error,app_not_found}
	end.

check2(App) ->
	case lists:keysearch(App,1,application:loaded_applications()) of
		{value,{App,_Desc,Ver}} -> 
			Version = version_to_tuple(Ver),
			check3(App,Version);
		false -> {error,app_not_loaded}
	end.

check3(App,Version) ->
	case lookup(App) of
		{ok,OnVersion} ->
			case compare(Version,OnVersion) of
				{ok,Status} -> {ok,Status,{Version,OnVersion}};
				{error,Reason} -> {error,Reason}
			end;
		{error,Reason} -> {error,Reason}
	end.


compare({V1,V2,V3},{V4,V5,V6}) ->
	<<Version1:24>> = <<V1:8,V2:8,V3:8>>,
	<<Version2:24>> = <<V4:8,V5:8,V6:8>>,
	if
		Version1 == Version2 -> {ok,current};
		Version1 > Version2  -> {ok,development};
		Version1 < Version2  -> {ok,upgrade};
		true -> {error,unknown_version_problem}
	end.

lookup(App) ->
	Host = atom_to_list(App) ++ ".erlsoft.net",
	case inet:getaddr(Host,inet) of
		{ok,{?IP_PREFIX,Version,SubVersion,Build}} -> {ok,{Version,SubVersion,Build}};
		{ok,{_,_,_,_}} -> {error,unknown_app}
	end.


version_to_tuple(Ver) ->
	case string:tokens(Ver,".") of
		[Version] -> {list_to_integer(Version),0,0};
		[Version,SubVersion] -> 
			{list_to_integer(Version),list_to_integer(SubVersion),0};
		[Version,SubVersion,Build] -> 
			{list_to_integer(Version),list_to_integer(SubVersion),list_to_integer(Build)};
		_Other -> _Other
	end.

version_to_list({V,S,B}) -> integer_to_list(V) ++ "." ++ integer_to_list(S) ++ "." ++ integer_to_list(B);
version_to_list({V,S})   -> integer_to_list(V) ++ "." ++ integer_to_list(S) ++ ".0";
version_to_list({V})     -> integer_to_list(V) ++ ".0.0".



get(App) ->
	case lookup(App) of
		{ok,Ver} ->
			AppName = atom_to_list(App),
			OnFile = "http://" ++ AppName ++ ".googlecode.com/files/" ++ AppName ++ "-" ++ version_to_list(Ver) ++ ".tar.gz",
			OnFile;
		{error,Reason} -> {error,Reason}
	end.

















